home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Graphics 2D / Restore Screen Cluts / MenuHandler.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  13.2 KB  |  426 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        MenuHandler.c
  3.  
  4.     Contains:    Menu-handling routines
  5.  
  6.     Written by: Forrest Tanaka    
  7.  
  8.     Copyright:    Copyright © 1988-1999 by Apple Computer, Inc., All Rights Reserved.
  9.  
  10.                 You may incorporate this Apple sample source code into your program(s) without
  11.                 restriction. This Apple sample source code has been provided "AS IS" and the
  12.                 responsibility for its operation is yours. You are not permitted to redistribute
  13.                 this Apple sample source code as "Apple sample source code" after having made
  14.                 changes. If you're going to re-distribute the source, we require that you make
  15.                 it clear in the source that the code was descended from Apple sample source
  16.                 code, but that you've made changes.
  17.  
  18.     Change History (most recent first):
  19.                 7/13/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  20.                 
  21.  
  22. */
  23.  
  24.  
  25. /******************************************************************************\
  26. * Header Files
  27. \******************************************************************************/
  28.  
  29. #ifndef THINK_C
  30. #include <Desk.h>
  31. #include <Errors.h>
  32. #include <Memory.h>
  33. #include <Menus.h>
  34. #include <Resources.h>
  35. #endif
  36.  
  37. #include "ColorReset.h"
  38. #include "MenuHandler.h"
  39. #include "PictDocument.h"
  40.  
  41.  
  42. /******************************************************************************\
  43. * Constants
  44. \******************************************************************************/
  45.  
  46. #define rMenuBar 128 /* Resource ID of this application’s MBAR resource */
  47.  
  48. #define kNumMenuGuides (mLastMenu - mApple + 1) /* Number of menu guide recs */
  49.  
  50.  
  51. /******************************************************************************\
  52. * Types
  53. \******************************************************************************/
  54.  
  55. typedef struct
  56. {
  57.     MenuHandle theMenu; /* Handle to this guide’s menu */
  58.     long       enables; /* Current enable flags */
  59. } MenuGuide;
  60.  
  61.  
  62. /******************************************************************************\
  63. * Prototypes
  64. \******************************************************************************/
  65.  
  66. void DoAppleMenu(
  67.     short menuItem);
  68.  
  69. void DoFileMenu(
  70.     short menuItem);
  71.  
  72. void DoEditMenu(
  73.     short menuItem);
  74.  
  75. void DoDisplayMenu(
  76.     short menuItem);
  77.  
  78. void ResetMenuItems(void);
  79.  
  80. void FixDAMenus(void);
  81.  
  82.  
  83. /******************************************************************************\
  84. * Variables
  85. \******************************************************************************/
  86.  
  87. MenuGuide gMenuGuides[kNumMenuGuides]; /* Application’s menu guide records */
  88.  
  89.  
  90. /******************************************************************************\
  91. * Public: StartMenus
  92. *
  93. * The menu guide array is initialized with the menu handles and enable flags of
  94. * all menus.
  95. *
  96. * If GetNewMBar couldn’t load the MBAR resource, then it returns nil and the
  97. * error code is in ResError, and I can deal with the error elegantly.  But, if
  98. * the GetNewMBar couldn’t load the menus themselves, then it’ll probably crash.
  99. \******************************************************************************/
  100.  
  101. OSErr StartMenus()
  102. {
  103.     Handle menuBar;   /* Handle to the menu bar from the MBAR resource */
  104.     short  menuIndex; /* Index into menu guide records */
  105.     OSErr  error;
  106.  
  107.     /* Load in the menu bar */
  108.     menuBar = GetNewMBar( rMenuBar );
  109.     if (menuBar != nil)
  110.     {
  111.         /* Set it, then dispose of it because SetMenuBar makes a copy */
  112.         SetMenuBar( menuBar );
  113.         DisposeHandle( menuBar );
  114.  
  115.         /* Add the desk accessories to the Apple menu */
  116.         AppendResMenu( GetMenuHandle( mApple ), 'DRVR' );
  117.  
  118.         /* Initialize the menu guide array */
  119.         for (menuIndex = 0; menuIndex < kNumMenuGuides; menuIndex++)
  120.         {
  121.             gMenuGuides[menuIndex].theMenu = GetMenuHandle( menuIndex + mApple );
  122.             gMenuGuides[menuIndex].enables = (**gMenuGuides[menuIndex].
  123.                     theMenu).enableFlags;
  124.         }
  125.  
  126.         /* Draw the menu bar */
  127.         DrawMenuBar();
  128.         error = noErr;
  129.     }
  130.     else
  131.     {
  132.         error = ResError();
  133.         if (error == noErr)
  134.             error = resNotFound;
  135.         if (error != resNotFound && error != memFullErr)
  136.             error = dsSysErr;
  137.     }
  138.     return error;
  139. }
  140.  
  141.  
  142. /******************************************************************************\
  143. * Public: DoMenuChoice
  144. *
  145. * This routine should be self-explanatory.
  146. \******************************************************************************/
  147.  
  148. void DoMenuChoice(
  149.     long menuChoice) /* Return value from MenuSelect or MenuKey */
  150. {
  151.     short menuNum;  /* Menu number of chosen menu */
  152.     short menuItem; /* Item number of chosen menu item */
  153.  
  154.     if (menuChoice != 0)
  155.     {
  156.         /* Get the chosen menu item and menu number */
  157.         menuNum = hiWord( menuChoice );
  158.         menuItem = loWord( menuChoice );
  159.  
  160.         /* Dispatch the appropriate menu-handling routine */
  161.         if (menuNum == mApple)
  162.             DoAppleMenu( menuItem );
  163.         else if (menuNum == mFile)
  164.             DoFileMenu( menuItem );
  165.         else if (menuNum == mEdit)
  166.             DoEditMenu( menuItem );
  167.         else if (menuNum == mDisplay)
  168.             DoDisplayMenu( menuItem );
  169.         HiliteMenu( 0 );
  170.     }
  171. }
  172.  
  173.  
  174. /******************************************************************************\
  175. * Private: DoAppleMenu - Handle an Apple menu item choice
  176. *
  177. * This routine is called whenever it’s determined that the chosen menu item was
  178. * in the Apple menu.  If the chosen menu item that’s passed in the menuItem
  179. * parameter wasn’t the About item, the name of the menu item is retrieved and
  180. * then OpenDeskAcc is called with this name so that the desk accessory by that
  181. * name is opened.  The Process Manager can launch desk accessories, but
  182. * OpenDeskAcc should still be used if the user chooses any item in the Apple
  183. * menu.
  184. \******************************************************************************/
  185.  
  186. static void DoAppleMenu(
  187.     short menuItem) /* Chosen menu item */
  188. {
  189.     Str255 daName; /* Name of the chosen DA */
  190.     short  refNum; /* Reference number of the DA, ignored */
  191.  
  192.     if (menuItem != iAbout)
  193.     {
  194.         GetMenuItemText( GetMenuHandle( mApple ), menuItem, /*<*/daName );
  195.         refNum = OpenDeskAcc( daName );
  196.     }
  197. }
  198.  
  199.  
  200. /******************************************************************************\
  201. * Private: DoFileMenu - Handle a File menu item choice
  202. *
  203. * This routine is called whenever it’s determined that the chosen menu item was
  204. * in the File menu.  The item number of the chosen menu item is passed in the
  205. * menuItem parameter.
  206. \******************************************************************************/
  207.  
  208. static void DoFileMenu(
  209.     short menuItem) /* Chosen menu item */
  210. {
  211.     if (menuItem == iOpen)
  212.         (void)DoOpenPictDoc();
  213.     else if (menuItem == iClose)
  214.     {
  215.         if (IsPictDocWindow( FrontWindow() ))
  216.             DoClosePictDoc( FrontWindow() );
  217.     }
  218.     else if (menuItem == iSaveAs)
  219.     {
  220.         if (IsPictDocWindow( FrontWindow() ))
  221.             DoSaveAsPictDoc( FrontWindow() );
  222.     }
  223.     else if (menuItem == iQuit)
  224.         DoQuit();
  225. }
  226.  
  227.  
  228. /******************************************************************************\
  229. * Private: DoEditMenu - Handle a Edit menu item choice
  230. *
  231. * This routine is called whenever it’s determined that the chosen menu item was
  232. * in the Edit menu.  The item number of the chosen menu item is passed in the
  233. * menuItem parameter.
  234. \******************************************************************************/
  235.  
  236. static void DoEditMenu(
  237.     short menuItem) /* Chosen menu item */
  238. {
  239.     SystemEdit( menuItem - 1 );
  240. }
  241.  
  242.  
  243. /******************************************************************************\
  244. * Private: DoEditMenu - Handle a Edit menu item choice
  245. *
  246. * This routine is called whenever it’s determined that the chosen menu item was
  247. * in the Edit menu.  The item number of the chosen menu item is passed in the
  248. * menuItem parameter.
  249. \******************************************************************************/
  250.  
  251. static void DoDisplayMenu(
  252.     short menuItem) /* Chosen menu item */
  253. {
  254.     if (menuItem == 1)
  255.         RestoreColorsPalette();
  256.     else if (menuItem == 2)
  257.         RestoreColorsSlam();
  258. }
  259.  
  260.  
  261. /******************************************************************************\
  262. * Public: FixMenus
  263. *
  264. * FixMenus first disables every available menu item.  Then the most basic menu
  265. * items are enabled.  The windowKind field of the front window is then checked.
  266. * If there is a window open, FixMenus calls a routine that’s responsible for
  267. * that kind of window to enable any menu items that are relevant to that kind of
  268. * window.
  269. *
  270. * If the front window is a modal dialog, then the basic set of menu items are
  271. * ! enabled, and the entire Apple menu is disabled.
  272. *
  273. * After this is done, the menu bar might have to be redrawn to reflect the new
  274. * conditions.  So, FixMenus go through every menu to determine if the state of
  275. * the entire menu has changed.  The MenuGuide records are used to help determine
  276. * this.  If the state of any many has changed, then the menu bar is redrawn.
  277. \******************************************************************************/
  278.  
  279. void FixMenus()
  280. {
  281.     WindowPtr  currWindow; /* Pointer to the front-most window */
  282.     MenuHandle aMenu;      /* Handle to menu being enabled */
  283.     long       oldEnables; /* True if 1+ items enabled when FixMenus called */
  284.     long       newEnables; /* True if 1+ items enabled after menus fixed */
  285.     Boolean    mustRedraw; /* True if menu bar has to be redrawn */
  286.     short      numItems;   /* Number of items in a menu */
  287.     short      menuIndex;  /* Index into menu guide array */
  288.  
  289.     /* Start by disabling all menus */
  290.     ResetMenuItems();
  291.  
  292.     /* Front-most window determines most menu enabling/disabling */
  293.     currWindow = FrontWindow();
  294.  
  295.     /* Depending on the type of the front window, enable appropriate items */
  296.     if (IsDAWindow( currWindow ))
  297.         FixDAMenus();
  298.     else if (IsPictDocWindow( currWindow ))
  299.         FixPictDocMenus( currWindow );
  300.  
  301.     /* Enable some menus */
  302.     aMenu = GetMenuHandle( mFile );
  303.     EnableItem( aMenu, iOpen );
  304.  
  305.     /* Assume we don’t have to redraw the menu bar */
  306.     mustRedraw = false;
  307.  
  308.     /* Check through every menu to see if there are any enabled items in it */
  309.     for (menuIndex = 0; menuIndex < kNumMenuGuides; menuIndex++)
  310.     {
  311.         /* Grab the old and new enable flags excluding flag for entire menu */
  312.         oldEnables = gMenuGuides[menuIndex].enables & 0xFFFFFFFE;
  313.         newEnables = (**gMenuGuides[menuIndex].theMenu).enableFlags &
  314.                 0xFFFFFFFE;
  315.  
  316.         /* Shift left so that we only see flags for existing items */
  317.         numItems = CountMItems(gMenuGuides [menuIndex].theMenu);
  318.         oldEnables = oldEnables << (31 - numItems);
  319.         newEnables = newEnables << (31 - numItems);
  320.  
  321.         /* Determine if the menu bar must be redrawn */
  322.         if (((oldEnables != 0) && (newEnables == 0)) || numItems == 0)
  323.         {
  324.             /* Had some items enabled, now has no items enabled, redraw */
  325.             DisableItem( gMenuGuides[menuIndex].theMenu, 0 );
  326.             mustRedraw = true;
  327.         }
  328.         else if ((oldEnables == 0) && (newEnables != 0))
  329.         {
  330.             /* Had no items enabled, now has some items enabled, redraw */
  331.             EnableItem( gMenuGuides[menuIndex].theMenu, 0) ;
  332.             mustRedraw = true;
  333.         }
  334.  
  335.         /* Update our copy of the enable flags */
  336.         gMenuGuides[menuIndex].enables = (**gMenuGuides[menuIndex].theMenu).
  337.                 enableFlags;
  338.     }
  339.  
  340.     /* If at least one menu has changed state, must redraw the menu bar */
  341.     if (mustRedraw)
  342.         DrawMenuBar();
  343. }
  344.  
  345.  
  346. /******************************************************************************\
  347. * Private: ResetMenuItems - Disable any disableable items and clear marks
  348. *
  349. * Disabling all the menu items is done bruteforcedly.  It could easily be done
  350. * by looping through each menu and disabling every item that comes up (disabling
  351. * the Font menu is done this way), but I thought doing it using the brute-force
  352. * method was clearer.  Then again. . .
  353. \******************************************************************************/
  354.  
  355. static void ResetMenuItems ()
  356. {
  357.     MenuHandle aMenu; /* Handle to each menu we’re disabling */
  358.  
  359.     /* Disable items in the File menu */
  360.     aMenu = GetMenuHandle( mFile );
  361.     DisableItem( aMenu, iOpen );
  362.     DisableItem( aMenu, iClose );
  363.     DisableItem( aMenu, iSaveAs );
  364.  
  365.     /* Disable items in the Edit menu */
  366.     aMenu = GetMenuHandle( mEdit );
  367.     DisableItem( aMenu, iUndo );
  368.     DisableItem( aMenu, iCut );
  369.     DisableItem( aMenu, iCopy );
  370.     DisableItem( aMenu, iPaste );
  371.     DisableItem( aMenu, iClear );
  372. }
  373.  
  374.  
  375. /******************************************************************************\
  376. * Private: FixDAMenus - Enable any menu items relevant for desk accessories
  377. *
  378. * Desk accessories can use the Edit menu, so the standard Edit menu items are
  379. * enabled.
  380. \******************************************************************************/
  381.  
  382. static void FixDAMenus()
  383. {
  384.     MenuHandle aMenu; /* Handle to each menu we’re enabling */
  385.  
  386.     /* Disable items in the Process menu */
  387.     aMenu = GetMenuHandle( mEdit );
  388.     EnableItem( aMenu, iUndo );
  389.     EnableItem( aMenu, iCut );
  390.     EnableItem( aMenu, iCopy );
  391.     EnableItem( aMenu, iPaste );
  392.     EnableItem( aMenu, iClear );
  393. }
  394.  
  395.  
  396. /******************************************************************************\
  397. * Public: DisableAllMenus
  398. *
  399. \******************************************************************************/
  400.  
  401. void DisableAllMenus()
  402. {
  403.     short menuIndex; /* Index into menu guide array */
  404.  
  405.     /* Check through every menu to see if there are any enabled items in it */
  406.     for (menuIndex = 0; menuIndex < kNumMenuGuides; menuIndex++)
  407.         DisableItem( gMenuGuides[menuIndex].theMenu, 0 );
  408. }
  409.  
  410. /******************************************************************************\
  411. * Public: RestoreAllMenus
  412. *
  413. \******************************************************************************/
  414.  
  415. void ReenableAllMenus()
  416. {
  417.     short menuIndex; /* Index into menu guide array */
  418.  
  419.     /* Check through every menu to see if there are any enabled items in it */
  420.     for (menuIndex = 0; menuIndex < kNumMenuGuides; menuIndex++)
  421.         if ( gMenuGuides[menuIndex].enables & 1 )
  422.             EnableItem( gMenuGuides[menuIndex].theMenu, 0 );
  423. }
  424.